package main

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/aliyun/fc-runtime-go-sdk/fc"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var (
	db    *gorm.DB
	sqlDB *sql.DB
)

type QueryParams struct {
	SchoolId string `json:"school_id,omitempty"`
	Time     string `json:"time,omitempty"`
}

type Student struct {
	StuId        string    `json:"stu_id,omitempty"`
	StuLoginname string    `json:"stu_loginname,omitempty"`
	SchoolId     string    `json:"school_id,omitempty"`
	StuRegTime   time.Time `json:"stu_reg_time,omitempty"`
}

func (Student) TableName() string {
	return "student"
}

func initialize(ctx context.Context) {
	dbUser := os.Getenv("MYSQL_USER")
	dbPassword := os.Getenv("MYSQL_PASSWORD")
	dbEndpoint := os.Getenv("MYSQL_ENDPOINT")
	dbPort := os.Getenv("MYSQL_PORT")
	dbName := os.Getenv("MYSQL_DBNAME")
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", dbUser, dbPassword, dbEndpoint, dbPort, dbName)
	
	var err error
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Printf("ERROR: Could not connect to MySQL instance: %v", err)
		return
	}
	
	sqlDB, err = db.DB()
	if err != nil {
		log.Printf("ERROR: Could not get database connection pool: %v", err)
		return
	}
	
	// 设置连接池
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Hour)
	
	log.Println("Database connection initialized successfully")
}

func handleError(w http.ResponseWriter, err error, statusCode int) {
	w.WriteHeader(statusCode)
	w.Header().Set("Content-Type", "application/json")
	errorResponse := map[string]string{"error": err.Error()}
	json.NewEncoder(w).Encode(errorResponse)
}

type Response struct {
	Message string `json:"message"`
	Count   int64  `json:"count,omitempty"`
}


func HandleHttpRequest(w http.ResponseWriter, req *http.Request) {

    w.Header().Set("Content-Type", "application/json")

    switch req.Method {
    case "GET":
        response := Response{Message: "Hello from Go HTTP Function!, Get Method"}
        w.WriteHeader(http.StatusOK)
        json.NewEncoder(w).Encode(response)
        return 

    case "POST":
        body, err := io.ReadAll(req.Body)
        if err != nil {
            handleError(w, fmt.Errorf("failed to read request body: %v", err), http.StatusBadRequest)
            return 
        }
        _ = req.Body.Close()

        var params QueryParams
        err = json.Unmarshal(body, &params)
        if err != nil {
            handleError(w, fmt.Errorf("failed to parse JSON: %v", err), http.StatusBadRequest)
            return 
        }

        // 检查数据库连接
        if db == nil {
            initialize(req.Context()) // 使用 req.Context()
            if db == nil {
                handleError(w, fmt.Errorf("database not initialized"), http.StatusInternalServerError)
                return 
            }
        }

        query := db.Model(&Student{})
        if params.SchoolId != "" {
            query = query.Where("school_id = ?", params.SchoolId)
        }
        if params.Time != "" {
            parseTime, err := time.Parse("2006-01-02", params.Time)
            if err != nil {
                handleError(w, fmt.Errorf("invalid time format, expected YYYY-MM-DD: %v", err), http.StatusBadRequest)
                return 
            }
            query = query.Where("stu_reg_time >= ?", parseTime)
        }

        var count int64
        result := query.Count(&count)
        if result.Error != nil {
            handleError(w, fmt.Errorf("database query failed: %v", result.Error), http.StatusInternalServerError)
            return
        }

        response := Response{
            Message: "Query successful",
            Count:   count,
        }
        w.WriteHeader(http.StatusOK)
        json.NewEncoder(w).Encode(response)
        return 

    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
        response := Response{Message: "Method not allowed"}
        json.NewEncoder(w).Encode(response)
        return 
    }
}

func preStop(ctx context.Context) {
	if sqlDB != nil {
		err := sqlDB.Close()
		if err != nil {
			log.Printf("ERROR: Could not close MySQL connection: %v", err)
		} else {
			log.Println("Database connection closed successfully")
		}
	}
}

func main() {
	fc.RegisterInitializerFunction(initialize)
	fc.RegisterPreStopFunction(preStop)
	fc.Start(HandleHttpRequest)

}